library(DNAcopy)
library(foreach)
library(plyr)
library(dplyr)
source("R/CNV_functions_AKS12202017.R")
Introduction
The following code generates figures for the Halobacterium CNV manuscript. This code uses the CNV package DNAcopy to analyze both gene expression and ChIP microarrays.
## All gene expression microarrays (numbers are standardized z scores)
all_data <- read.delim(file = "data/Gene_expression_Master.txt", row.names = 1)
## Empty array to be filled for the generation of segment maps
rarray <- read.delim(file = "data/rarray_allloci.txt")
GE microarray data analysis
The following commented chunk takes a long time to run. A preprocessed object, provided in the github data/ folder, can be loaded instead (see below).
# CNA.ob <- CNA(all_data[,1:1154], all_data$Chr, all_data$Start,data.type = 'logratio', sampleid = colnames(all_data)[1:1154])
# smoothed <- smooth.CNA(CNA.ob)
# segsmot <- segment(smoothed, verbose = 0) ## Set verbose = 1 if number of arrays is not huge
# save(segsmot, file = "data/segmented_GE_arrays.Rdata")
load(file = "data/segmented_GE_arrays.Rdata")
Figure 3 - GE segmentation up vs downregulation on main chromosome
chromosome, 20kb cutoff, Fig 3A

Calcluate functional enrichment in large GE frequency peaks on chromosome, fig 3B
#Find segments present in >= 5% of arrays, determine functional enrichments in chromosome
ge20k.5<-subset(t1f20k.split[[1]], (Thresh_up + Threshdown) >= 58)
#analysis in this code chunk relies upon https://github.com/amyschmid/histone_arCOG. Load source from there.
GE.5percent.arcog<-cogtest2(ge20k.5$GeneName, cogs, 0.05)
write.table (GE.5percent.arcog, file = "data/ge20k_freqpks_5percent_arCOGs.txt", sep = "\t") #Supplementary table?
#Determine which genes are in which arCOG categories, save as supplementary tables
ge20k.5.pk1<-cogset(ge20k.5$GeneName, cogs, "Cell motility ")
write.table (ge20k.5.pk1, file = "ge20k_freqpks_5percent_pk1genes.txt",sep = "\t")
ge20k.5.pk2<-cogset(ge20k.5$GeneName, cogs, "Translation; ribosomal structure and biogenesis ")
write.table (ge20k.5.pk2, file = "ge20k_freqpks_5percent_pk2.txt", sep = "\t")
ge20k.5.pk3<-cogset(ge20k.5$GeneName, cogs, "Coenzyme transport and metabolism ")
write.table (ge20k.5.pk3, file = "ge20k_freqpks_5percent_pk3.txt", sep = "\t")
#similar code was used to calculate enrichments in gene expression data frequency peaks for megaplsmids from t1f20k.split[[2]] and t1f20k.split[[3]] except at 5k threshold.
ChIP microarray data analysis
Samples were parsed, median-centered, scaled, and segmented in independent batches before combining. The following code takes segmented chip array data and creates composite maps.
## Read in segmented ChIP data
test <- read.delim(file = "data/all_clone_fragments_chIP.txt")
## Read in Trmb file 12 for example segmentation output
load(file = "data/trmb12.Rdata")
Example segmentation output, Trmb12 array
shown in Figure 1 example of genomic break point detection in ChIP arrays using DNAcopy
Analyzing: Trmb.12

Table 1: How many CNVs were detected in each array (GE and ChIP data)?
## First we consider GE data. Filter segments by significance across main chromosome.
all.clone.segs.GE<- segsmot$output
all.clone.segs.GE$seg.length <- (all.clone.segs.GE$loc.end - all.clone.segs.GE$loc.start)
segs.GE.20k <- subset (all.clone.segs.GE, seg.length >=20000)
segs.GE.20k <- subset (segs.GE.20k, chrom == "Chr" & (seg.mean >= 1 | seg.mean <= -1))
#for pNRC200
#segs.GE.20k.p200 <- subset (all.clone.segs.GE, seg.length >=20000)
segs.GE.20k.p200 <- subset (segs.GE.20k.p200, chrom == "pNRC200" & (seg.mean >= 1 | seg.mean <= -1))
#for pNRC100
#segs.GE.20k.p100 <- subset (all.clone.segs.GE, seg.length >=20000)
segs.GE.20k.p100 <- subset (segs.GE.20k.p100, chrom == "pNRC100" & (seg.mean >= 1 | seg.mean <= -1))
## Determine how many significant segments were contained within which GE arrays on main chromosome
freq.per.array20 <- plyr:::count(segs.GE.20k, "ID")
hist(freq.per.array20$freq, col = "grey", main = "Distribution of putative CNVs within each GE array", xlab = "Number of arrays")
#for pNRC100
freq.per.array20.p100 <- plyr:::count(segs.GE.20k.p100, "ID")
hist(freq.per.array20.p100$freq, col = "grey", main = "Distribution of putative CNVs within each GE array", xlab = "Number of arrays")
#for pNRC200
freq.per.array20.p200 <- plyr:::count(segs.GE.20k.p200, "ID")
hist(freq.per.array20.p200$freq, col = "grey", main = "Distribution of putative CNVs within each GE array", xlab = "Number of arrays")
## Next we consider chip data. Filter segments by significance at 5k threshold
test$seg.length <- (test$loc.end - test$loc.start)
segs.chip.5k <- subset (test, seg.length >= 5000)
segs.chip.5k <- subset (segs.chip.5k, chrom == "Chr" & (seg.mean >= 0.5 | seg.mean <= -0.5))
## Determine how many significant segments were contained within which ChIP arrays
freq.per.array.chip.5 <- plyr:::count(segs.chip.5k, "ID")
hist(freq.per.array.chip.5$freq, col = "grey", main = "Distribution of putative CNVs within each ChIP array", xlab = "Number of arrays")

Figure 5
Frequency map of all ChIP CNVs, with IS elements marked
sig.per.array<-read.delim ("data/num_signif_segs_per_arrays.txt")
hist(sig.per.array$total.signif.segs.per.array, breaks = 12, col = "grey", xlab = "Number CNVs per array", main = "CNVs are frequent")

Fig 5A: IS elements are detected within CNV regions.
Fig 5B: IS elements are associated with CNV regions at higher rate than expected by chance: bootstrapping results
plotchr_chip2(copymap = chip.split, narrays = 48, ymax = 80, ish_table = ish)
legend('topleft',legend=c('CNV','IS', '10% threshold'),col=c('black',rgb(0.1,0.1,.8,.3), 'red'),cex=1.2,bg='white', lty=c(1,2),lwd=2)
abline(h = 10, col = "red")

#points(x = sample(peaks7, 1000), y = c(rep(2,1000)), col = "green", pch =16, cex= .5)
Appendix
hist(ish.boot, col = "gray", xlim = c(0,15), xlab = "Number of IS elements\n in CNV regions", cex.lab=1.2, breaks =10)
abline( v = 14, lty = 2)

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.
LS0tCnRpdGxlOiAiSGFsb19DTlZfZmlndXJlX2NvZGVfRklOQUwiCmRhdGU6ICJKYW51YXJ5IDE5IDIwMTgiCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKYXV0aG9yczogS2VlbHkgRHVsbWFnZSBhbmQgQW15IFNjaG1pZAotLS0KCgpgYGB7cn0KbGlicmFyeShETkFjb3B5KQpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkocGx5cikKbGlicmFyeShkcGx5cikKCnNvdXJjZSgiUi9DTlZfZnVuY3Rpb25zX0FLUzEyMjAyMDE3LlIiKQpgYGAKCgoKIyMgSW50cm9kdWN0aW9uCgpUaGUgZm9sbG93aW5nIGNvZGUgZ2VuZXJhdGVzIGZpZ3VyZXMgZm9yIHRoZSBIYWxvYmFjdGVyaXVtIENOViBtYW51c2NyaXB0LiAgVGhpcyBjb2RlIHVzZXMgdGhlIENOViBwYWNrYWdlIEROQWNvcHkgdG8gYW5hbHl6ZSBib3RoIGdlbmUgZXhwcmVzc2lvbiBhbmQgQ2hJUCBtaWNyb2FycmF5cy4KCmBgYHtyfQojIyBBbGwgZ2VuZSBleHByZXNzaW9uIG1pY3JvYXJyYXlzIChudW1iZXJzIGFyZSBzdGFuZGFyZGl6ZWQgeiBzY29yZXMpCmFsbF9kYXRhIDwtIHJlYWQuZGVsaW0oZmlsZSA9ICJkYXRhL0dlbmVfZXhwcmVzc2lvbl9NYXN0ZXIudHh0Iiwgcm93Lm5hbWVzID0gMSkKCiMjIEVtcHR5IGFycmF5IHRvIGJlIGZpbGxlZCBmb3IgdGhlIGdlbmVyYXRpb24gb2Ygc2VnbWVudCBtYXBzCnJhcnJheSA8LSByZWFkLmRlbGltKGZpbGUgPSAiZGF0YS9yYXJyYXlfYWxsbG9jaS50eHQiKQoKYGBgCgoKCiMjIEdFIG1pY3JvYXJyYXkgZGF0YSBhbmFseXNpcwoKVGhlIGZvbGxvd2luZyBjb21tZW50ZWQgY2h1bmsgdGFrZXMgYSBsb25nIHRpbWUgdG8gcnVuLiAgQSBwcmVwcm9jZXNzZWQgb2JqZWN0LCBwcm92aWRlZCBpbiB0aGUgZ2l0aHViIGRhdGEvIGZvbGRlciwgY2FuIGJlIGxvYWRlZCBpbnN0ZWFkIChzZWUgYmVsb3cpLgpgYGB7ciwgbWVzc2FnZSA9IEZ9CiMgQ05BLm9iIDwtIENOQShhbGxfZGF0YVssMToxMTU0XSwgYWxsX2RhdGEkQ2hyLCBhbGxfZGF0YSRTdGFydCxkYXRhLnR5cGUgPSAnbG9ncmF0aW8nLCBzYW1wbGVpZCA9IGNvbG5hbWVzKGFsbF9kYXRhKVsxOjExNTRdKSAKIyBzbW9vdGhlZCA8LSBzbW9vdGguQ05BKENOQS5vYikKIyBzZWdzbW90IDwtIHNlZ21lbnQoc21vb3RoZWQsIHZlcmJvc2UgPSAwKSAgIyMgU2V0IHZlcmJvc2UgPSAxIGlmIG51bWJlciBvZiBhcnJheXMgaXMgbm90IGh1Z2UKIyBzYXZlKHNlZ3Ntb3QsIGZpbGUgPSAiZGF0YS9zZWdtZW50ZWRfR0VfYXJyYXlzLlJkYXRhIikKYGBgCmBgYHtyfQpsb2FkKGZpbGUgPSAiZGF0YS9zZWdtZW50ZWRfR0VfYXJyYXlzLlJkYXRhIikKYGBgCgojIyMgRmlndXJlIDIsIGZyZXF1ZW5jeSBtYXAgcGxvdHMgZm9yIG1lZ2FwbGFzbWlkcyBwTlJDMTAwIGFuZCBwTlJDMjAwCgpHZW5lcmF0ZSBtYXBzIG9mIHNlZ21lbnRzIGF0IGRpZmZlcmVudCBmcmFnbWVudCBzaXplIHRocmVzaG9sZHMKYGBge3J9CnQxZjVrLmNvcHkgPC0gY29weW1hcDQocmVmX2FycmF5ID0gcmFycmF5LCBzZWdfYXJyYXkgPSBzZWdzbW90JG91dHB1dCwgdGhyZXNob2xkID0gMSwgZi5zaXplID0gNTAwMCkKdDFmMTBrLmNvcHkgPC0gY29weW1hcDQocmVmX2FycmF5ID0gcmFycmF5LCBzZWdfYXJyYXkgPSBzZWdzbW90JG91dHB1dCwgdGhyZXNob2xkID0gMSwgZi5zaXplID0gMTAwMDApCnQxZjIway5jb3B5IDwtIGNvcHltYXA0KHJlZl9hcnJheSA9IHJhcnJheSwgc2VnX2FycmF5ID0gc2Vnc21vdCRvdXRwdXQsIHRocmVzaG9sZCA9IDEsIGYuc2l6ZSA9IDIwMDAwKQp0MWY1MGsuY29weSA8LSBjb3B5bWFwNChyZWZfYXJyYXkgPSByYXJyYXksIHNlZ19hcnJheSA9IHNlZ3Ntb3Qkb3V0cHV0LCB0aHJlc2hvbGQgPSAxLCBmLnNpemUgPSA1MDAwMCkKdDFmMTAway5jb3B5IDwtIGNvcHltYXA0KHJlZl9hcnJheSA9IHJhcnJheSwgc2VnX2FycmF5ID0gc2Vnc21vdCRvdXRwdXQsIHRocmVzaG9sZCA9IDEsIGYuc2l6ZSA9IDEwMDAwMCkKYGBgCgpTcGxpdCBjb3B5IG1hcHMgYnkgZ2Vub21pYyBlbGVtZW50cwpgYGB7cn0KdDFmNWsuc3BsaXQgPC0gc3BsaXQyKHQxZjVrLmNvcHkpCnQxZjEway5zcGxpdCA8LSBzcGxpdDIodDFmMTBrLmNvcHkpCnQxZjIway5zcGxpdCA8LSBzcGxpdDIodDFmMjBrLmNvcHkpCnQxZjUway5zcGxpdCA8LSBzcGxpdDIodDFmNTBrLmNvcHkpCnQxZjEwMGsuc3BsaXQgPC0gc3BsaXQyKHQxZjEwMGsuY29weSkKYGBgCgpwTlJDMTAwIGJ5IGdlbmUgZXhwcmVzc2lvbiBzZWdtZW50IHNpemUgZnJlcXVlbmN5LCBmaWd1cmUgMkEgbGVmdApgYGB7ciBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gNSwgZWNobyA9IEZ9CnBsb3RjaHIuY29sKHQxZjVrLnNwbGl0W1syXV0sMTE1NCwzNSwgJ29yYW5nZScpCmFkZF9jb3B5cGxvdCh0MWYxMGsuc3BsaXRbWzJdXSwxMTU0LCdncmVlbicpCmFkZF9jb3B5cGxvdCh0MWYyMGsuc3BsaXRbWzJdXSwxMTU0LCdibHVlJykKYWRkX2NvcHlwbG90KHQxZjUway5zcGxpdFtbMl1dLDExNTQsJ3B1cnBsZScpCmFkZF9jb3B5cGxvdCh0MWYxMDBrLnNwbGl0W1syXV0sMTE1NCwnYmxhY2snKQpsZWdlbmQoJ3RvcHJpZ2h0JywgY29sPWMoJ29yYW5nZScsJ2dyZWVuJywnYmx1ZScsJ3B1cnBsZScsJ2JsYWNrJyksIGxlZ2VuZD1jKCc1IGtiJywnMTAga2InLCAnMjAga2InLCc1MCBrYicsJzEwMCBrYicpLCBsd2Q9MywgYmc9J3doaXRlJywgY2V4PTEuMikKYGBgCgpwTlJDMjAwIGJ5IGdlbmUgZXhwcmVzc2lvbiBzZWdtZW50IHNpemUgZnJlcXVlbmN5LCBmaWd1cmUgMkEgcmlnaHQKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQpwbG90Y2hyLmNvbCh0MWY1ay5zcGxpdFtbM11dLDExNTQsMTAsICdvcmFuZ2UnKQphZGRfY29weXBsb3QodDFmMTBrLnNwbGl0W1szXV0sMTE1NCwnZ3JlZW4nKQphZGRfY29weXBsb3QodDFmMjBrLnNwbGl0W1szXV0sMTE1NCwnYmx1ZScpCmFkZF9jb3B5cGxvdCh0MWY1MGsuc3BsaXRbWzNdXSwxMTU0LCdwdXJwbGUnKQphZGRfY29weXBsb3QodDFmMTAway5zcGxpdFtbM11dLDExNTQsJ2JsYWNrJykKI2xlZ2VuZCgndG9wcmlnaHQnLCBjb2w9Yygnb3JhbmdlJywnZ3JlZW4nLCdibHVlJywncHVycGxlJywnYmxhY2snKSwgbGVnZW5kPWMoJzUga2InLCcxMCBrYicsICcyMCBrYicsJzUwIGtiJywnMTAwIGtiJyksIGx3ZD0zLCBiZz0nd2hpdGUnLCBjZXg9MS4yKQp0ZXh0KDE3NTAwMCwgOC4yLCAgY2V4ID0gMSwgZm9udCA9IDIgKQp0ZXh0ICgzMjUwMDAsIDguMiwgbGFiZWwgPSAyLCBjZXggPSAxLCBmb250PSAyKQpgYGAKCgpwTlJDMTAwIHVwIGFuZCBkb3ducmVndWxhdGVkIHNlZ21lbnQgZnJlcXVlbmN5IG1hcCwgRmlndXJlIDJCIGxlZnQKYGBge3IgZmlnLndpZHRoID0gNSwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQojIyByZWdpb25zIDIwa2Igb3IgbGFyZ2VyLCB0aHJlc2hvbGQgb2YgMSAKcGxvdHBsYXMuR0UyKGNvcHltYXAgPSB0MWYyMGsuc3BsaXRbWzJdXSwgbmFycmF5cyA9IDExNTQsIHlyYW5nZSA9IGMoMCwxMCkpCmBgYAoKcE5SQzIwMCB1cCBhbmQgZG93bnJlZ3VsYXRlZCBzZWdtZW50IGZyZXF1ZW5jeSBtYXAsIEZpZ3VyZSAyQiByaWdodApgYGB7ciBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gNSwgZWNobyA9IEZ9CiMjIHJlZ2lvbnMgMjBrYiBvciBsYXJnZXIsIHRocmVzaG9sZCBvZiAxIApwbG90cGxhcy5HRTIoY29weW1hcCA9IHQxZjIway5zcGxpdFtbM11dLCBuYXJyYXlzID0gMTE1NCwgeXJhbmdlID0gYygwLDEwKSkKYGBgCgojIyMgRmlndXJlIDMgLSBHRSBzZWdtZW50YXRpb24gdXAgdnMgZG93bnJlZ3VsYXRpb24gb24gbWFpbiBjaHJvbW9zb21lCgpjaHJvbW9zb21lLCAyMGtiIGN1dG9mZiwgRmlnIDNBCmBgYHtyIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA1LCBlY2hvID0gRn0KIyMgcmVnaW9ucyAyMGtiIG9yIGxhcmdlciwgdGhyZXNob2xkIG9mIDEgCnBsb3RwbGFzLkdFMihjb3B5bWFwID0gdDFmMjBrLnNwbGl0W1sxXV0sIG5hcnJheXMgPSAxMTU0LCB5cmFuZ2UgPSBjKDAsMTApKQpgYGAKCkNhbGNsdWF0ZSBmdW5jdGlvbmFsIGVucmljaG1lbnQgaW4gbGFyZ2UgR0UgZnJlcXVlbmN5IHBlYWtzIG9uIGNocm9tb3NvbWUsIGZpZyAzQgpgYGB7cn0KI0ZpbmQgc2VnbWVudHMgcHJlc2VudCBpbiA+PSA1JSBvZiBhcnJheXMsIGRldGVybWluZSBmdW5jdGlvbmFsIGVucmljaG1lbnRzIGluIGNocm9tb3NvbWUKZ2UyMGsuNTwtc3Vic2V0KHQxZjIway5zcGxpdFtbMV1dLCAoVGhyZXNoX3VwICsgVGhyZXNoZG93bikgPj0gNTgpCgojY29nc2V0IGFuZCBjb2d0ZXN0IGZ1bmN0aW9ucyBhbHNvIGF2YWlsYWJsZSB2aWEgaHR0cHM6Ly9naXRodWIuY29tL2FteXNjaG1pZC9oaXN0b25lX2FyQ09HIGFuZCBEdWxtYWdlIGV0IGFsLiwgMjAxNSBtQmlvLgoKR0UuNXBlcmNlbnQuYXJjb2c8LWNvZ3Rlc3QyKGdlMjBrLjUkR2VuZU5hbWUsIGNvZ3MsIDAuMDUpCndyaXRlLnRhYmxlIChHRS41cGVyY2VudC5hcmNvZywgZmlsZSA9ICJkYXRhL2dlMjBrX2ZyZXFwa3NfNXBlcmNlbnRfYXJDT0dzLnR4dCIsIHNlcCA9ICJcdCIpICNTdXBwbGVtZW50YXJ5IHRhYmxlPwojRGV0ZXJtaW5lIHdoaWNoIGdlbmVzIGFyZSBpbiB3aGljaCBhckNPRyBjYXRlZ29yaWVzLCBzYXZlIGFzIHN1cHBsZW1lbnRhcnkgdGFibGVzIApnZTIway41LnBrMTwtY29nc2V0KGdlMjBrLjUkR2VuZU5hbWUsIGNvZ3MsICJDZWxsIG1vdGlsaXR5ICIpCndyaXRlLnRhYmxlIChnZTIway41LnBrMSwgZmlsZSA9ICJnZTIwa19mcmVxcGtzXzVwZXJjZW50X3BrMWdlbmVzLnR4dCIsc2VwID0gIlx0IikKZ2UyMGsuNS5wazI8LWNvZ3NldChnZTIway41JEdlbmVOYW1lLCBjb2dzLCAiVHJhbnNsYXRpb247IHJpYm9zb21hbCBzdHJ1Y3R1cmUgYW5kIGJpb2dlbmVzaXMgIikKd3JpdGUudGFibGUgKGdlMjBrLjUucGsyLCBmaWxlID0gImdlMjBrX2ZyZXFwa3NfNXBlcmNlbnRfcGsyLnR4dCIsIHNlcCA9ICJcdCIpCmdlMjBrLjUucGszPC1jb2dzZXQoZ2UyMGsuNSRHZW5lTmFtZSwgY29ncywgIkNvZW56eW1lIHRyYW5zcG9ydCBhbmQgbWV0YWJvbGlzbSAiKQp3cml0ZS50YWJsZSAoZ2UyMGsuNS5wazMsIGZpbGUgPSAiZ2UyMGtfZnJlcXBrc181cGVyY2VudF9wazMudHh0Iiwgc2VwID0gIlx0IikKCiNzaW1pbGFyIGNvZGUgd2FzIHVzZWQgdG8gY2FsY3VsYXRlIGVucmljaG1lbnRzIGluIGdlbmUgZXhwcmVzc2lvbiBkYXRhIGZyZXF1ZW5jeSBwZWFrcyBmb3IgbWVnYXBsc21pZHMgZnJvbSB0MWYyMGsuc3BsaXRbWzJdXSBhbmQgdDFmMjBrLnNwbGl0W1szXV0gZXhjZXB0IGF0IDVrIHRocmVzaG9sZC4KYGBgCgojIyBDaElQIG1pY3JvYXJyYXkgZGF0YSBhbmFseXNpcwoKU2FtcGxlcyB3ZXJlIHBhcnNlZCwgbWVkaWFuLWNlbnRlcmVkLCBzY2FsZWQsIGFuZCBzZWdtZW50ZWQgaW4gaW5kZXBlbmRlbnQgYmF0Y2hlcyBiZWZvcmUgY29tYmluaW5nLiAgVGhlIGZvbGxvd2luZyBjb2RlIHRha2VzIHNlZ21lbnRlZCBjaGlwIGFycmF5IGRhdGEgYW5kIGNyZWF0ZXMgY29tcG9zaXRlIG1hcHMuCmBgYHtyfQojIyBSZWFkIGluIHNlZ21lbnRlZCBDaElQIGRhdGEgCnRlc3QgPC0gcmVhZC5kZWxpbShmaWxlID0gImRhdGEvYWxsX2Nsb25lX2ZyYWdtZW50c19jaElQLnR4dCIpCiMjIFJlYWQgaW4gVHJtYiBmaWxlIDEyIGZvciBleGFtcGxlIHNlZ21lbnRhdGlvbiBvdXRwdXQKbG9hZChmaWxlID0gImRhdGEvdHJtYjEyLlJkYXRhIikKYGBgCgojIyMgRXhhbXBsZSBzZWdtZW50YXRpb24gb3V0cHV0LCBUcm1iMTIgYXJyYXkgCgpzaG93biBpbiBGaWd1cmUgMSBleGFtcGxlIG9mIGdlbm9taWMgYnJlYWsgcG9pbnQgZGV0ZWN0aW9uIGluIENoSVAgYXJyYXlzIHVzaW5nIEROQWNvcHkKYGBge3IgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA1LCBlY2hvID0gRn0KdHJtYjEyLmNuYSA8LSBDTkEoZ2Vub21kYXQgPSBhcy5udW1lcmljKHRybWIxMi5tJFNjYWxlZCksIGNocm9tID0gdHJtYjEyLm0kQ2hyLCBtYXBsb2MgPSBhcy5udW1lcmljKHRybWIxMi5tJFBvc2l0aW9uKSwgc2FtcGxlaWQgPSAiVHJtYiAxMiIpCnRybWIxMi5zbW9vdGggPC0gc21vb3RoLkNOQSh0cm1iMTIuY25hKQp0cm1iMTIuc2Vnc21vdCA8LSBzZWdtZW50KHRybWIxMi5zbW9vdGgpCmNvcHlwbG90LmNoci5hbHQodHJtYjEyLnNlZ3Ntb3QsIGMoLTIsOCkpCmBgYAoKCgojIyMgRmlndXJlIDQKU2VnbWVudCBncmVxdWVuY3kgbWFwIG9mIENoSVAgQ05WcyBhY3Jvc3MgNDggYXJyYXlzLCBjYXRlZ29yaXplZCBieSBkZXBsZXRpb24gYW5kIGFtcGxpZmljYXRpb24gZXZlbnRzCmBgYHtyfQojIEdlbmVyYXRlIGNvcHltYXAKY3JhcnJheSA8LSByZWFkLmRlbGltKGZpbGUgPSAiZGF0YS9yYXJyYXlfMjQwMF9tb3ZlZF9wcm9iZXMudHh0IikKY3JhcnJheSA8LSBkcm9wbGV2ZWxzKGNyYXJyYXlbY3JhcnJheSRDaHIgPT0gIkNociIsXSkKCiM1ayB0aHJlc2hvbGQKY2hpcC5jb3B5IDwtIGNvcHltYXA0KHJlZl9hcnJheSA9IGNyYXJyYXksIHNlZ19hcnJheSA9IHRlc3QsIHRocmVzaG9sZCA9IDAuNSwgZi5zaXplID0gNTAwMCkKY2hpcC5zcGxpdCA8LSBzcGxpdDIoY2hpcC5jb3B5KVtbMV1dICU+JSBkcGx5cjo6YXJyYW5nZShTdGFydCkKCmBgYAoKIyMjIyBGaWd1cmUgNEEKRnJlcXVlbmN5IG1hcCBvZiBhbGwgQ2hJUCBDTlZzLCA1ayB0aHJlc2hvbGQsIDEwJSBhcnJheSB0aHJlc2hvbGQsIDE2IHBrcyBtYXJrZWQuCmBgYHtyIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gNSwgZWNobyA9IEZ9CnBsb3RjaHIoY2hpcC5zcGxpdCwgNDgsIDgwKQphYmxpbmUgKGggPSAxMCwgY29sID0gInJlZCIpCnBrcy4xNjwtcmVhZC5kZWxpbSAoImRhdGEvQ2hJUF8xNnBrc19mb3JSLnR4dCIsIHNlcD0gIlx0IikKYWJsaW5lICh2ID0gcGtzLjE2JHBrLmNlbnRlciwgY29sID0gImdyZXkiKQp0ZXh0KChwa3MuMTYkcGsuY2VudGVyKSwgNzAsIGxhYmVscyA9IGMoMToxNiksICBjZXggPSAwLjgsIGZvbnQgPSAyICkKYGBgCgojIyMjIEZpZyA0QgpgYGB7ciBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQpwbG90cGxhcy5jaGlwKGNoaXAuc3BsaXQsIDQ4LCB5cmFuZ2UgPSBjKDAsODApKQojbGVnZW5kKCd0b3BsZWZ0JyxsZWdlbmQ9YygnQW1wbGlmaWNhdGlvbicsJ0RlcGxldGlvbicpLGNvbD1jKCdjeWFuJywnYmx1ZScpLGNleD0wLjgsYmc9J3doaXRlJywgbHR5PWMoMSwxKSxsd2Q9MikKYGBgCgoKIyMjIFRhYmxlIDE6IEhvdyBtYW55IENOVnMgd2VyZSBkZXRlY3RlZCBpbiBlYWNoIGFycmF5IChHRSBhbmQgQ2hJUCBkYXRhKT8KYGBge3J9CiMjIEZpcnN0IHdlIGNvbnNpZGVyIEdFIGRhdGEuIEZpbHRlciBzZWdtZW50cyBieSBzaWduaWZpY2FuY2UgYWNyb3NzIG1haW4gY2hyb21vc29tZS4KYWxsLmNsb25lLnNlZ3MuR0U8LSBzZWdzbW90JG91dHB1dAphbGwuY2xvbmUuc2Vncy5HRSRzZWcubGVuZ3RoIDwtIChhbGwuY2xvbmUuc2Vncy5HRSRsb2MuZW5kIC0gYWxsLmNsb25lLnNlZ3MuR0UkbG9jLnN0YXJ0KQpzZWdzLkdFLjIwayA8LSBzdWJzZXQgKGFsbC5jbG9uZS5zZWdzLkdFLCBzZWcubGVuZ3RoID49MjAwMDApCnNlZ3MuR0UuMjBrIDwtIHN1YnNldCAoc2Vncy5HRS4yMGssIGNocm9tID09ICJDaHIiICYgKHNlZy5tZWFuID49IDEgfCBzZWcubWVhbiA8PSAtMSkpCiNmb3IgcE5SQzIwMAojc2Vncy5HRS4yMGsucDIwMCA8LSBzdWJzZXQgKGFsbC5jbG9uZS5zZWdzLkdFLCBzZWcubGVuZ3RoID49MjAwMDApCnNlZ3MuR0UuMjBrLnAyMDAgPC0gc3Vic2V0IChzZWdzLkdFLjIway5wMjAwLCBjaHJvbSA9PSAicE5SQzIwMCIgJiAoc2VnLm1lYW4gPj0gMSB8IHNlZy5tZWFuIDw9IC0xKSkKI2ZvciBwTlJDMTAwCiNzZWdzLkdFLjIway5wMTAwIDwtIHN1YnNldCAoYWxsLmNsb25lLnNlZ3MuR0UsIHNlZy5sZW5ndGggPj0yMDAwMCkKc2Vncy5HRS4yMGsucDEwMCA8LSBzdWJzZXQgKHNlZ3MuR0UuMjBrLnAxMDAsIGNocm9tID09ICJwTlJDMTAwIiAmIChzZWcubWVhbiA+PSAxIHwgc2VnLm1lYW4gPD0gLTEpKQoKIyMgRGV0ZXJtaW5lIGhvdyBtYW55IHNpZ25pZmljYW50IHNlZ21lbnRzIHdlcmUgY29udGFpbmVkIHdpdGhpbiB3aGljaCBHRSBhcnJheXMgb24gbWFpbiBjaHJvbW9zb21lCmZyZXEucGVyLmFycmF5MjAgPC0gcGx5cjo6OmNvdW50KHNlZ3MuR0UuMjBrLCAiSUQiKQpoaXN0KGZyZXEucGVyLmFycmF5MjAkZnJlcSwgY29sID0gImdyZXkiLCBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBwdXRhdGl2ZSBDTlZzIHdpdGhpbiBlYWNoIEdFIGFycmF5IiwgeGxhYiA9ICJOdW1iZXIgb2YgYXJyYXlzIikgCgojZm9yIHBOUkMxMDAKZnJlcS5wZXIuYXJyYXkyMC5wMTAwIDwtIHBseXI6Ojpjb3VudChzZWdzLkdFLjIway5wMTAwLCAiSUQiKQpoaXN0KGZyZXEucGVyLmFycmF5MjAucDEwMCRmcmVxLCBjb2wgPSAiZ3JleSIsIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIHB1dGF0aXZlIENOVnMgd2l0aGluIGVhY2ggR0UgYXJyYXkiLCB4bGFiID0gIk51bWJlciBvZiBhcnJheXMiKSAKCiNmb3IgcE5SQzIwMApmcmVxLnBlci5hcnJheTIwLnAyMDAgPC0gcGx5cjo6OmNvdW50KHNlZ3MuR0UuMjBrLnAyMDAsICJJRCIpCmhpc3QoZnJlcS5wZXIuYXJyYXkyMC5wMjAwJGZyZXEsIGNvbCA9ICJncmV5IiwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgcHV0YXRpdmUgQ05WcyB3aXRoaW4gZWFjaCBHRSBhcnJheSIsIHhsYWIgPSAiTnVtYmVyIG9mIGFycmF5cyIpIAoKYGBgCgpgYGB7cn0KIyMgTmV4dCB3ZSBjb25zaWRlciBjaGlwIGRhdGEuIEZpbHRlciBzZWdtZW50cyBieSBzaWduaWZpY2FuY2UgYXQgNWsgdGhyZXNob2xkCnRlc3Qkc2VnLmxlbmd0aCA8LSAodGVzdCRsb2MuZW5kIC0gdGVzdCRsb2Muc3RhcnQpCnNlZ3MuY2hpcC41ayA8LSBzdWJzZXQgKHRlc3QsIHNlZy5sZW5ndGggPj0gNTAwMCkKc2Vncy5jaGlwLjVrIDwtIHN1YnNldCAoc2Vncy5jaGlwLjVrLCBjaHJvbSA9PSAiQ2hyIiAmIChzZWcubWVhbiA+PSAwLjUgfCBzZWcubWVhbiA8PSAtMC41KSkKCiMjIERldGVybWluZSBob3cgbWFueSBzaWduaWZpY2FudCBzZWdtZW50cyB3ZXJlIGNvbnRhaW5lZCB3aXRoaW4gd2hpY2ggQ2hJUCBhcnJheXMgCmZyZXEucGVyLmFycmF5LmNoaXAuNSA8LSBwbHlyOjo6Y291bnQoc2Vncy5jaGlwLjVrLCAiSUQiKQpoaXN0KGZyZXEucGVyLmFycmF5LmNoaXAuNSRmcmVxLCBjb2wgPSAiZ3JleSIsIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIHB1dGF0aXZlIENOVnMgd2l0aGluIGVhY2ggQ2hJUCBhcnJheSIsIHhsYWIgPSAiTnVtYmVyIG9mIGFycmF5cyIpCgpgYGAKCiMjIEZpZ3VyZSA1CkZyZXF1ZW5jeSBtYXAgb2YgYWxsIENoSVAgQ05Wcywgd2l0aCBJUyBlbGVtZW50cyBtYXJrZWQKCmBgYHtyfQojIyByZWFkIGluIElTSCB0YWJsZQppc2ggPC0gcmVhZC5kZWxpbShmaWxlID0gImRhdGEvMjAxNzA3MDNfSVNmaW5kZXJfSVNIX2VsZW1lbnRzLnR4dCIpCiMjIHJlYWQgaW4gcGVha3MgdmVjdG9yCnBlYWtzIDwtbG9hZCgiZGF0YS9DaGlwX3BlYWtfcmVnaW9ucy5SZGF0YSIpCmBgYAoKRmlnIDVBOiBJUyBlbGVtZW50cyBhcmUgZGV0ZWN0ZWQgd2l0aGluIENOViByZWdpb25zLgpgYGB7ciBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQpwbG90Y2hyX2NoaXAyKGNvcHltYXAgPSBjaGlwLnNwbGl0LCBuYXJyYXlzID0gNDgsIHltYXggPSA4MCwgaXNoX3RhYmxlID0gaXNoKQpsZWdlbmQoJ3RvcGxlZnQnLGxlZ2VuZD1jKCdDTlYnLCdJUycsICcxMCUgdGhyZXNob2xkJyksY29sPWMoJ2JsYWNrJyxyZ2IoMC4xLDAuMSwuOCwuMyksICdyZWQnKSxjZXg9MS4yLGJnPSd3aGl0ZScsIGx0eT1jKDEsMiksbHdkPTIpCmFibGluZShoID0gMTAsIGNvbCA9ICJyZWQiKQojcG9pbnRzKHggPSBzYW1wbGUocGVha3M3LCAxMDAwKSwgeSA9IGMocmVwKDIsMTAwMCkpLCBjb2wgPSAiZ3JlZW4iLCBwY2ggPTE2LCBjZXg9IC41KQoKYGBgCgoKRmlnIDVCOiBJUyBlbGVtZW50cyBhcmUgYXNzb2NpYXRlZCB3aXRoIENOViByZWdpb25zIGF0IGhpZ2hlciByYXRlIHRoYW4gZXhwZWN0ZWQgYnkgY2hhbmNlOiBib290c3RyYXBwaW5nIHJlc3VsdHMKYGBge3J9CnNldC5zZWVkKDg4NzYpCklTYm9vdCA8LSBmdW5jdGlvbihJU19udW1iZXIsIHBlYWtzKXsKCWJvb3Q9YygpCglmb3IoaSBpbiAxOjEwMDAwKXsKCUlTbGlzdD0gc2FtcGxlKDE6MjAxNDIzOSxJU19udW1iZXIpCQogCWJvb3RbaV09IGxlbmd0aCh3aGljaChJU2xpc3QgJWluJSBwZWFrcykpCgl9Cglib290Cn0KCiMjIG9mIElTIGVsZW1lbnRzIGluIGNociBwZWFrcyBmcm9tIENoSVAgZGF0YSAobm90ZTogSVMgdGFibGUgaXMgZm9yIGNocm9tb3NvbWUgb25seSkKaXMubiA8LSBsZW5ndGgoaXNoJFN0YXJ0W2lzaCRTdGFydCAlaW4lIHBlYWtzN10pCgppc2guYm9vdCA8LSBJU2Jvb3QoaXMubiwgcGVha3M3KQoKYGBgCmBgYHtyIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTQsIGVjaG89Rn0KaGlzdChpc2guYm9vdCwgY29sID0gImdyYXkiLCB4bGltID0gYygwLDE1KSwgeGxhYiA9ICJOdW1iZXIgb2YgSVMgZWxlbWVudHNcbiBpbiBDTlYgcmVnaW9ucyIsIGNleC5sYWI9MS4yLCBicmVha3MgPTEwKQphYmxpbmUoIHYgPSAxNCwgbHR5ID0gMikKYGBgCgoKIyMgQXBwZW5kaXgKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgoKTm90ZSB0aGF0IHRoZSBgZWNobyA9IEZBTFNFYCBwYXJhbWV0ZXIgd2FzIGFkZGVkIHRvIHRoZSBjb2RlIGNodW5rIHRvIHByZXZlbnQgcHJpbnRpbmcgb2YgdGhlIFIgY29kZSB0aGF0IGdlbmVyYXRlZCB0aGUgcGxvdC4K